package com.wfh.wfhwx.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wfh.wfhwx.exception.BusinessException;
import com.wfh.wfhwx.exception.ErrorCode;
import com.wfh.wfhwx.model.dto.WxReplyContentDTO;
import com.wfh.wfhwx.model.dto.WxReplyMatchValueDTO;
import com.wfh.wfhwx.model.dto.WxReplyRulePageQueryRequest;
import com.wfh.wfhwx.model.entity.User;
import com.wfh.wfhwx.model.entity.WxReplyRule;
import com.wfh.wfhwx.model.enums.WxReplyContentTypeEnum;
import com.wfh.wfhwx.model.enums.WxReplyMatchTypeEnum;
import com.wfh.wfhwx.model.enums.WxReplyRuleTypeEnum;
import com.wfh.wfhwx.model.vo.WxReplyRuleVO;
import com.wfh.wfhwx.service.UserService;
import com.wfh.wfhwx.service.WxReplyRuleService;
import com.wfh.wfhwx.mapper.WxReplyRuleMapper;
import jakarta.annotation.Resource;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author fenghuanwang
* @description 针对表【wx_reply_rule(微信公众号回复规则)】的数据库操作Service实现
* @createDate 2025-06-20 16:23:18
*/
@Service
public class WxReplyRuleServiceImpl extends ServiceImpl<WxReplyRuleMapper, WxReplyRule>
    implements WxReplyRuleService{

    @Resource
    private UserService userService;

    /**
     * 构建查询条件
     *
     * @param wxReplyRulePageQueryRequest
     * @return
     */
    @Override
    public LambdaQueryWrapper<WxReplyRule> getQueryWrapper(WxReplyRulePageQueryRequest wxReplyRulePageQueryRequest) {
        // 参数校验
        if (ObjectUtils.isEmpty(wxReplyRulePageQueryRequest)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        String appId = wxReplyRulePageQueryRequest.getAppId();
        String ruleName = wxReplyRulePageQueryRequest.getRuleName();
        String matchValue = wxReplyRulePageQueryRequest.getMatchValue();
        String eventKey = wxReplyRulePageQueryRequest.getEventKey();
        String replyContent = wxReplyRulePageQueryRequest.getReplyContent();
        String ruleDescription = wxReplyRulePageQueryRequest.getRuleDescription();
        Integer replyType = wxReplyRulePageQueryRequest.getReplyType();
        String sortField = wxReplyRulePageQueryRequest.getSortField();
        String sortOrder = wxReplyRulePageQueryRequest.getSortOrder();
        LambdaQueryWrapper<WxReplyRule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(!ObjectUtils.isEmpty(appId), WxReplyRule::getAppId, appId)
                .eq(!ObjectUtils.isEmpty(ruleName), WxReplyRule::getRuleName, ruleName)
                .eq(!ObjectUtils.isEmpty(matchValue), WxReplyRule::getMatchValue, matchValue)
                .eq(!ObjectUtils.isEmpty(eventKey), WxReplyRule::getEventKey, eventKey)
                .eq(!ObjectUtils.isEmpty(replyContent), WxReplyRule::getReplyContent, replyContent)
                .eq(!ObjectUtils.isEmpty(ruleDescription), WxReplyRule::getRuleDescription, ruleDescription)
                .eq(!ObjectUtils.isEmpty(replyType), WxReplyRule::getReplyType, replyType)
                .orderByAsc(!ObjectUtils.isEmpty(sortField) && "asc".equals(sortOrder), WxReplyRule::getCreateTime)
                .orderByDesc(!ObjectUtils.isEmpty(sortField) && "desc".equals(sortOrder), WxReplyRule::getCreateTime);
        return queryWrapper;
    }

    /**
     * 获取分页数据
     * @param wxReplyRulePage
     * @param queryWrapper
     * @return
     */
    @Override
    public Page<WxReplyRuleVO> getPage(Page<WxReplyRule> wxReplyRulePage, LambdaQueryWrapper<WxReplyRule> queryWrapper) {
        Page<WxReplyRule> page = this.page(wxReplyRulePage, queryWrapper);
        Set<Long> userIdSer = wxReplyRulePage.getRecords().stream()
                .map(WxReplyRule::getUserId)
                .collect(Collectors.toSet());
        Map<Long, User> userMap;
        if(ObjectUtils.isNotEmpty(userIdSer)){
            userMap = userService.listByIds(userIdSer).stream()
                    .collect(Collectors.toMap(User::getId, user -> user));
        }else {
            userMap = Map.of();
        }
        BeanUtils.copyProperties(page, wxReplyRulePage, "records");
        Page<WxReplyRuleVO> wxReplyRulePageVO = new Page<>();
        wxReplyRulePageVO.setRecords(
                wxReplyRulePage.getRecords().stream()
                        .map(wxReplyRule -> {
                            WxReplyRuleVO wxReplyRuleVO = WxReplyRuleVO.obj2VO(wxReplyRule);
                            User user = userMap.get(wxReplyRule.getUserId());
                            if (ObjectUtils.isNotEmpty(user)) {
                                wxReplyRuleVO.setUser(userService.getUserVO(user));
                            }
                            return wxReplyRuleVO;

                        }
        ).collect(Collectors.toList()));
        return wxReplyRulePageVO;
    }

    /**
     * 根据用户的消息匹配回复内容
     * @param appId
     * @param msg
     * @return
     */
    @Override
    public WxReplyContentDTO receiveMessageReply(String appId, String msg) {
        // 1、将所有的关键词规则和默认规则都查询出来
        WxReplyRule keyWordReply = this.list(
                        Wrappers.lambdaQuery(WxReplyRule.class)
                                .eq(WxReplyRule::getAppId, appId)
                                .in(WxReplyRule::getReplyType,
                                        WxReplyRuleTypeEnum.KEYWORDS.getValue(), WxReplyRuleTypeEnum.DEFAULT.getValue())
                                .orderByDesc(WxReplyRule::getUpdateTime)
                ) // 2、将关键词都过滤出来
                .stream()
                .filter(wxReplyRule -> {
                    // 过滤非关键词类型的规则
                    if (!WxReplyRuleTypeEnum.KEYWORDS.getValue().equals(wxReplyRule.getReplyType())) {
                        return false;
                    }
                    // 解析匹配值为json为对象列表
                    List<WxReplyMatchValueDTO> wxReplyMatchValueDTOS = JSONUtil.toList(wxReplyRule.getMatchValue(), WxReplyMatchValueDTO.class);
                    // 查看当前规则的关键词是否包含在用户所发送的消息中
                    for (WxReplyMatchValueDTO wxReplyMatchValueDTO : wxReplyMatchValueDTOS) {
                        String matchKeyWords = wxReplyMatchValueDTO.getMatchKeyWords();
                        Integer matchType = wxReplyMatchValueDTO.getMatchType();
                        if (StringUtils.isBlank(matchKeyWords)) {
                            continue;
                        }
                        // 全匹配，用户发送的内容完全等于关键词（忽略大小写）
                        if (WxReplyMatchTypeEnum.FULL.getValue().equals(matchType) && msg.equalsIgnoreCase(msg)) {
                            return true;
                        }
                        // 半个匹配，用户发送的内容包含关键词（忽略大小写）
                        if (WxReplyMatchTypeEnum.PART.getValue().equals(matchType) && msg.contains(matchKeyWords)) {
                            return true;
                        }
                    }
                    return false;
                })
                .findFirst()
                .orElse(null);
        // 如果没有匹配上就返回默认的内容
        if (ObjectUtils.isEmpty(keyWordReply)) {
            return null;
        }
        return JSONUtil.toBean(keyWordReply.getReplyContent(), WxReplyContentDTO.class);
    }

    /**
     * 根据内容类型生成对应的微信回复消息
     * @param wxMpXmlMessage
     * @param wxReplyContentDTO
     * @param contentTypeEnum
     * @return
     */
    @Override
    public WxMpXmlOutMessage replyByContentType(WxMpXmlMessage wxMpXmlMessage, WxReplyContentDTO wxReplyContentDTO, WxReplyContentTypeEnum contentTypeEnum) {
        return switch (contentTypeEnum) {
            case TEXT -> WxMpXmlOutMessage
                    .TEXT()
                    .content(wxReplyContentDTO.getTextContent())
                    .fromUser(wxMpXmlMessage.getToUser())
                    .toUser(wxMpXmlMessage.getFromUser())
                    .build();
            case IMAGE -> WxMpXmlOutMessage
                    .IMAGE()
                    .mediaId(wxReplyContentDTO.getMediaId())
                    .fromUser(wxMpXmlMessage.getToUser())
                    .toUser(wxMpXmlMessage.getFromUser())
                    .build();
            case VOICE -> WxMpXmlOutMessage
                    .VOICE()
                    .mediaId(wxReplyContentDTO.getMediaId())
                    .fromUser(wxMpXmlMessage.getToUser())
                    .toUser(wxMpXmlMessage.getFromUser())
                    .build();
            case VIDEO -> WxMpXmlOutMessage
                    .VIDEO()
                    .mediaId(wxReplyContentDTO.getMediaId())
                    .fromUser(wxMpXmlMessage.getToUser())
                    .toUser(wxMpXmlMessage.getFromUser())
                    .build();
            case NEWS -> null;
        };
    }
}




